home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1998 November / Freeware November 1998.img / dist / fw_UDELxntp.idb / usr / freeware / src / xntp-3.4o-export / lib / dolfptoa.c.z / dolfptoa.c
C/C++ Source or Header  |  1998-01-21  |  3KB  |  162 lines

  1. /*
  2.  * dolfptoa - do the grunge work of converting an l_fp number to decimal
  3.  */
  4. #include <stdio.h>
  5.  
  6. #include "ntp_fp.h"
  7. #include "lib_strbuf.h"
  8. #include "ntp_string.h"
  9. #include "ntp_stdlib.h"
  10.  
  11. char *
  12. dolfptoa(fpi, fpv, neg, ndec, msec)
  13.     u_long fpi;
  14.     u_long fpv;
  15.     int neg;
  16.     int ndec;
  17.     int msec;
  18. {
  19.     register u_char *cp, *cpend;
  20.     register u_long lwork;
  21.     register int dec;
  22.     u_char cbuf[24];
  23.     u_char *cpdec;
  24.     char *buf;
  25.     char *bp;
  26.  
  27.     /*
  28.      * Get a string buffer before starting
  29.      */
  30.     LIB_GETBUF(buf);
  31.  
  32.     /*
  33.      * Zero the character buffer
  34.      */
  35.     memset((char *) cbuf, 0, sizeof(cbuf));
  36.  
  37.     /*
  38.      * Work on the integral part.  This is biased by what I know
  39.      * compiles fairly well for a 68000.
  40.      */
  41.     cp = cpend = &cbuf[10];
  42.     lwork = fpi;
  43.     if (lwork & 0xffff0000) {
  44.         register u_long lten = 10;
  45.         register u_long ltmp;
  46.  
  47.         do {
  48.             ltmp = lwork;
  49.             lwork /= lten;
  50.             ltmp -= (lwork << 3) + (lwork << 1);
  51.             *--cp = (u_char)ltmp;
  52.         } while (lwork & 0xffff0000);
  53.     }
  54.     if (lwork != 0) {
  55.         register u_short sten = 10;
  56.         register u_short stmp;
  57.         register u_short swork = (u_short)lwork;
  58.  
  59.         do {
  60.             stmp = swork;
  61.             swork /= sten;
  62.             stmp -= (swork<<3) + (swork<<1);
  63.             *--cp = (u_char)stmp;
  64.         } while (swork != 0);
  65.     }
  66.  
  67.     /*
  68.      * Done that, now deal with the problem of the fraction.  First
  69.      * determine the number of decimal places.
  70.      */
  71.     if (msec) {
  72.         dec = ndec + 3;
  73.         if (dec < 3)
  74.             dec = 3;
  75.         cpdec = &cbuf[13];
  76.     } else {
  77.         dec = ndec;
  78.         if (dec < 0)
  79.             dec = 0;
  80.         cpdec = &cbuf[10];
  81.     }
  82.     if (dec > 12)
  83.         dec = 12;
  84.     
  85.     /*
  86.      * If there's a fraction to deal with, do so.
  87.      */
  88.     if (fpv != 0) {
  89.         l_fp work;
  90.  
  91.         work.l_ui = 0;
  92.         work.l_uf = fpv;
  93.         while (dec > 0) {
  94.             l_fp ftmp;
  95.  
  96.             dec--;
  97.             /*
  98.              * The scheme here is to multiply the
  99.              * fraction (0.1234...) by ten.  This moves
  100.              * a junk of BCD into the units part.
  101.              * record that and iterate.
  102.              */
  103.             work.l_ui = 0;
  104.             L_LSHIFT(&work);
  105.             ftmp = work;
  106.             L_LSHIFT(&work);
  107.             L_LSHIFT(&work);
  108.             L_ADD(&work, &ftmp);
  109.             *cpend++ = (u_char)work.l_ui;
  110.             if (work.l_uf == 0)
  111.                 break;
  112.         }
  113.  
  114.         /*
  115.          * Rounding is rotten
  116.          */
  117.         if (work.l_uf & 0x80000000) {
  118.             register u_char *tp = cpend;
  119.  
  120.             *(--tp) += 1;
  121.             while (*tp >= 10) {
  122.                 *tp = 0;
  123.                 *(--tp) += 1;
  124.             };
  125.             if (tp < cp)
  126.                 cp = tp;
  127.         }
  128.     }
  129.     cpend += dec;
  130.  
  131.  
  132.     /*
  133.      * We've now got the fraction in cbuf[], with cp pointing at
  134.      * the first character, cpend pointing past the last, and
  135.      * cpdec pointing at the first character past the decimal.
  136.      * Remove leading zeros, then format the number into the
  137.      * buffer.
  138.      */
  139.     while (cp < cpdec) {
  140.         if (*cp != 0)
  141.             break;
  142.         cp++;
  143.     }
  144.     if (cp == cpdec)
  145.         --cp;
  146.  
  147.     bp = buf;
  148.     if (neg)
  149.         *bp++ = '-';
  150.     while (cp < cpend) {
  151.         if (cp == cpdec)
  152.             *bp++ = '.';
  153.         *bp++ = (char)(*cp++ + '0');    /* ascii dependent? */
  154.     }
  155.     *bp = '\0';
  156.  
  157.     /*
  158.      * Done!
  159.      */
  160.     return buf;
  161. }
  162.